/**
 * www.easyplatform.cn ©2016
 */
package cn.easyplatform.studio.interceptor;

import cn.easyplatform.entities.beans.ResourceBean;
import cn.easyplatform.entities.beans.project.ProjectBean;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.studio.StudioException;
import cn.easyplatform.studio.cfg.*;
import cn.easyplatform.studio.context.Contexts;
import cn.easyplatform.studio.dao.*;
import cn.easyplatform.studio.vos.LoginUserVo;
import cn.easyplatform.studio.web.editors.help.GuideConfigEditor;
import cn.easyplatform.utils.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;

import javax.sql.DataSource;
import java.util.Date;

/**
 * @author <a href="mailto:shiny_vc@163.com">陈云亮</a> <br/>
 * @since 2.0.0 <br/>
 */
public class CommandContext {

    private static Logger log = LoggerFactory.getLogger(CommandContext.class);

    private EngineConfiguration engineConfiguration;

    private Session session;

    private ProjectBean project;

    private LoginUserVo user;

    private TransactionContext tx;

    /**
     * @param engineConfiguration
     */
    public CommandContext(EngineConfiguration engineConfiguration) {
        this.engineConfiguration = engineConfiguration;
        session = Sessions.getCurrent();
        this.user = (LoginUserVo) session.getAttribute(Contexts.EP_USER);
        this.project = (ProjectBean) session.getAttribute(Contexts.EP_PROJECT);
        if (this.user != null)
            user.setLastAccessTime(new Date());
    }

    /**
     * 开始事务
     */
    public void beginTx() {
        tx = engineConfiguration.getTransactionContextFactory()
                .openTransactionContext(this);
        log.debug("begin transaction for {%s}", user.getUserId());
    }

    /**
     * 提交事务
     */
    public void commitTx() {
        Assert.notNull(tx,
                "this transactionContext is required; it must not be null");
        tx.commit();
        log.debug("commit transaction for {%s}", user.getUserId());
    }

    /**
     * 回滚事务
     */
    public void rollbackTx() {
        if (tx != null)
            tx.rollback();
        log.debug("rollback transaction for {%s}", user.getUserId());
    }

    /**
     * 关闭事务中的连接
     */
    public void closeTx() {
        if (tx != null) {
            tx.close();
            log.debug("close transaction for {%s}", user.getUserId());
        }
    }

    public LoginUserVo getUser() {
        return this.user;
    }

    public ProjectBean getProject() {
        return this.project;
    }

    public IdentityDao getIdentityDao() {
        return DaoFactory
                .createIdentityDao(engineConfiguration.getDatasource());
    }

    public BizDao getBizDao(String ds) {
        if (Strings.isBlank(ds))
            ds = project.getBizDb();
        ResourceBean rb = getEntityDao().getDatasource(ds);
        if (rb != null)
            return DaoFactory.createBizDao(engineConfiguration
                    .getDatasource(rb));
        else
            throw new StudioException(Labels.getLabel(
                    "app.datasource.not.found", new String[]{ds}));
    }

    public BizDao getBizDao() {
        return getBizDao(null);
    }

    public EntityDao getEntityDao() {
        return DaoFactory.createEntityDao(engineConfiguration.getDatasource());
    }

    public HisEntityDao getHisEntityDao() {
        return DaoFactory.createHisEntityDao(engineConfiguration.getDatasource());
    }

    public DataSource getDataSource() {
        return engineConfiguration.getDatasource();
    }

    public LoginlogDao getLoginlogDao() {
        return DaoFactory.createLoginlogDao(engineConfiguration.getDatasource());
    }

    public UploadHistDao getUploadHistDao() {
        return DaoFactory.createUploadHistDao(engineConfiguration.getDatasource());
    }

    public VersionDao getVersionDao() {
        return DaoFactory.createVersionDao(engineConfiguration.getDatasource());
    }

    public SeqDao getSeqDao() {
        return DaoFactory.createSeqDao(engineConfiguration.getDatasource());
    }

    public IdGenerator getIdGenerator() {
        return engineConfiguration.getIdGeneratorFactory().getIdGenerator(this);
    }

    public MobileConfDao getMobileConf() { return DaoFactory.createMobileConfDao(engineConfiguration.getDatasource());}

    public TaskLinkDao getTaskLink() {return DaoFactory.createTaskLinkDao(engineConfiguration.getDatasource());}

    public LinkDao getLink()
    {
        return DaoFactory.createLinkDao(engineConfiguration.getDatasource());
    }

    public GuideConfigDao getGuideConfig(GuideConfigEditor.GuideConfigType guideConfigType) {
        if (guideConfigType == GuideConfigEditor.GuideConfigType.GuideConfigStudio)
            return DaoFactory.createGuideConfigDao(engineConfiguration.getDatasource());
        else {
            String ds = project.getBizDb();
            ResourceBean rb = getEntityDao().getDatasource(ds);
            if (rb != null)
                return DaoFactory.createGuideConfigDao(engineConfiguration
                        .getDatasource(rb));
            else
                throw new StudioException(Labels.getLabel(
                        "app.datasource.not.found", new String[]{ds}));
        }
    }

    public ModuleDao getModule() {
        return DaoFactory.createModuleDao(engineConfiguration.getDatasource());
    }

    public DicDao getDicDao(String ds) {
        if (Strings.isBlank(ds))
            ds = project.getBizDb();
        ResourceBean rb = getEntityDao().getDatasource(ds);
        if (rb != null)
            return DaoFactory.createDicDao(engineConfiguration
                    .getDatasource(rb));
        else
            throw new StudioException(Labels.getLabel(
                    "app.datasource.not.found", new String[]{ds}));
    }

    public DicDetailDao getDicDetailDao(String ds) {
        if (Strings.isBlank(ds))
            ds = project.getBizDb();
        ResourceBean rb = getEntityDao().getDatasource(ds);
        if (rb != null)
            return DaoFactory.createDicDetailDao(engineConfiguration
                    .getDatasource(rb));
        else
            throw new StudioException(Labels.getLabel(
                    "app.datasource.not.found", new String[]{ds}));
    }

    public MessageInfoDao getMessageInfoDao(String ds) {
        if (Strings.isBlank(ds))
            ds = project.getBizDb();
        ResourceBean rb = getEntityDao().getDatasource(ds);
        if (rb != null)
            return DaoFactory.createMessageInfoDao(engineConfiguration
                    .getDatasource(rb));
        else
            throw new StudioException(Labels.getLabel(
                    "app.datasource.not.found", new String[]{ds}));
    }

    public MenuInfoDao getMenuInfoDao(String ds) {
        if (Strings.isBlank(ds))
            ds = project.getBizDb();
        ResourceBean rb = getEntityDao().getDatasource(ds);
        if (rb != null)
            return DaoFactory.createMenuInfoDao(engineConfiguration
                    .getDatasource(rb));
        else
            throw new StudioException(Labels.getLabel(
                    "app.datasource.not.found", new String[]{ds}));
    }

    public DatabaseUpdateDao getDatabaseUpdateDao() {
        return DaoFactory.createDatabaseUpdateDao(engineConfiguration
                .getDatasource());
    }

    public CustomWidgetDao getCustomWidgetDao() {
        return DaoFactory.createWidgetDao(engineConfiguration
                .getDatasource());
    }

    public SessionManager getSessionManager() {
        return engineConfiguration.getSessionManagerFactory()
                .getSessionManager(this);
    }

    public EntityLockProvider getEntityLockProvider() {
        return engineConfiguration.getEntityLockProviderFactory()
                .getEntityLockProvider(this);
    }


    public void logout(boolean normal) {
        engineConfiguration.getSessionManagerFactory().getSessionManager(this)
                .removeUser(user);
        if (normal) {
            engineConfiguration.getEntityLockProviderFactory()
                    .getEntityLockProvider(this).reset();
            session.invalidate();
        }
    }

    // 操作基于会话的属性
    public void setAttribute(String name, Object value) {
        session.setAttribute(name, value);
    }

    public Object getAttribute(String name) {
        return session.getAttribute(name);
    }

    public Object removeAttribute(String name) {
        return session.removeAttribute(name);
    }

    // 系统配置
    public int getConfigAsInt(String name) {
        return Nums.toInt(engineConfiguration.getConfig(name), 0);
    }

    public boolean getConfigAsBoolean(String name) {
        return engineConfiguration.getConfig(name) == null ? false
                : engineConfiguration.getConfig(name).equalsIgnoreCase("true");
    }

    public String getConfig(String name) {
        return engineConfiguration.getConfig(name);
    }

    // 操作系统公共属性
    public void setAppAttribute(String name, Object value) {
        engineConfiguration.setAttribute(name, value);
    }

    public Object getAppAttribute(String name) {
        return engineConfiguration.getAttribute(name);
    }

    public Object removeAppAttribute(String name) {
        return engineConfiguration.removeAttribute(name);
    }
}
